package wiiusej.apptest;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


import sun.font.CreatedFontTracker;
import wiiusej.*;
import wiiusej.apptest.activityTasks.ComClient;
import wiiusej.apptest.activityTasks.EnergyTransmisionTask;
import wiiusej.apptest.activityTasks.Spell;
import wiiusej.connection.ConnectionManager;
import wiiusej.connection.ShareConnectionCell;
import wiiusej.wiiusejevents.GenericEvent;
import wiiusej.wiiusejevents.utils.WiimoteListener;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.RootLogger;

public class WiimoteMain extends Thread{

	private static final int NTHREADS = 150;
	private static BlockingQueue<Spell> eneergyToComClient = new LinkedBlockingDeque<Spell>();
	
	
	
	
	private static final ExecutorService exec = 
		Executors.newFixedThreadPool(NTHREADS);
	
	private static HashMap<Integer, Wiimote> wiimotes;
	
	//Logger	
	private static Logger fileLogger;
	
	static Lock lock  = new ReentrantLock();	
	static Condition condition = lock.newCondition();
	
	
	public static void main(String[] args) {

		//Log configuration
		PropertyConfigurator.configure("log4j.properties");
		fileLogger = Logger.getLogger("main");
		
		//fileWriter is a WiimoteFileWriter which implements the WiimoteListener
		//interface.
		
		fileLogger.debug("Creating Barrier");
		CyclicBarrier barrier = new CyclicBarrier(2);
		
		//COM queue
		BlockingQueue<GenericEvent> queue = new LinkedBlockingQueue<GenericEvent>();
		
		//WiiUseApiManager.getInstance();
		//Wiimote[] wiimotes = WiiUseApiManager.getWiimotes(1, true);
		fileLogger.debug("Creating Shared Cell");
		ShareConnectionCell cell = new ShareConnectionCell();
		
		
		
		fileLogger.debug("Creating WiiUseApiManager");
		WiiUseApiManager controller = new WiiUseApiManager(cell, barrier, lock, condition, queue);
		controller.start();
		
		fileLogger.debug("Creating ConnectionManager");
		//we create a listener for wiimotes
		
		ConnectionManager connectionManager = new ConnectionManager(exec, cell, barrier, 
				controller, lock, condition, queue, eneergyToComClient);		
		
		connectionManager.start();
		
		
		/*
		//wait until get the lock
		lock2.lock();
		
		fileLogger.debug("Getting the lock");
		try{
			fileLogger.debug("Wait for condition");
			while(controller.getWiimotes() != null){
				condition2.await();				
			}
						
			fileLogger.debug("Signal Received for condition");
		} catch (InterruptedException e) {			
			e.printStackTrace();
		}finally{
			fileLogger.debug("Releasing the LOCK");
			lock2.unlock();
		}*/
		
		try {
			barrier.await();
		} catch (InterruptedException e1) {
			
			e1.printStackTrace();
		} catch (BrokenBarrierException e1) {
			e1.printStackTrace();
		}
		
		try{			
			wiimotes = controller.getWiimotes();
			
			if(wiimotes == null){
				fileLogger.debug("Wiimote NULL");
			}
			
			if(!wiimotes.isEmpty()){
				fileLogger.debug("Connected Found Devices: " + wiimotes.size());
				//createListeners(wiimotes);				  
			}else{
				fileLogger.debug("NO Connected devices were found");
			}
		
			
		}catch(Exception e){
			e.printStackTrace();
		}				
		
		initComClient();
		
	}		
		
	private static void initComClient(){
		
		Runnable clientServer = 
			new ComClient(eneergyToComClient, wiimotes);
		
		exec.execute(clientServer);
		
	}
	
	
}

	
